package capture
import javax.xml.parsers.SAXParserFactory
import org.xml.sax.*
import java.net.SocketException

public final class CaptureClient {

    Socket sock
    def reader
    XmlMessageHandler handler
    OptionManager options
    static boolean run = true
    static boolean connected = false


    private final static instance = new CaptureClient()

    private CaptureClient() {
        options = OptionManager.getInstance()
        handler = new XmlMessageHandler()
    }

    public static getInstance() {
        return instance
    }

    //sending message
    synchronized void send(String message) {
        try {
            def stream = sock.getOutputStream()
            stream << message + '\n'
            stream.flush()
        } catch (SocketException e) {
            run = false
            println "${new Date().format('HH:mm:ss')} $e.localizedMessage [$options.serverIp:$options.serverPort]"
        }

    }

    //connects to server and passes input stream to xmlparser
    void connect() throws SocketException {
        sock = new Socket()
        sock.connect(new InetSocketAddress(options.serverIp, options.serverPort), options.socketTimeout)
        reader = SAXParserFactory.newInstance().newSAXParser().XMLReader
        sock.withStreams { input, output ->
            def t = 0;

            while (run) {
                def msg = '';

                while ((t = input.read()) != '\0' && t != -1) {
                    msg += (char) t;
                }

                if (t < 0) break

                try {
                    reader.setContentHandler(handler)
                    reader.parse(new InputSource(new StringReader(msg)))
                }
                catch (SAXParseException spe) {
                    println "${new Date().format('HH:mm:ss')} SAX Exception: $spe.localizedMessage"
                    return
                }

            }
            println "${new Date().format('HH:mm:ss')} Socket disconnected."

        }
    }


    public static void main(String[] args) {
        OptionManager options = OptionManager.getInstance()
        CaptureClient cc = CaptureClient.getInstance()

        if (args.length < 8) {
            println "${new Date().format('HH:mm:ss')} Too few arguments. Usage: -s  <serv_ip> -p <serv_port> -a <servId> -b <clientId>"
            return
        }
        options.serverIp = args[1]
        options.serverPort = args[3].toInteger()
        options.serverId = args[5].toLong()
        options.id = args[7].toLong()

        println "Current working dir: " + System.getenv('PWD')
        //two more parameters specyfying file and process exclusion list path, may be hardcoded in starting script for eg, or in next versions
        //sent by server
        options.loadExclusionList("${args.length == 10?args[8]:'FileMonitor.exl'}",ExclusionListType.FILE)
        options.loadExclusionList("${args.length == 10?args[9]:'ProcessMonitor.exl'}",ExclusionListType.PROCESS)

        while (run && !connected) {
            try {
                cc.connect()
                connected = true
            }
            catch (ConnectException e) {
                println "${new Date().format('HH:mm:ss')} $e.localizedMessage [$options.serverIp:$options.serverPort]"
                Thread.sleep(5000)
            }
            catch (SocketTimeoutException e) {
                println "${new Date().format('HH:mm:ss')} $e.localizedMessage [$options.serverIp:$options.serverPort]"
                Thread.sleep(5000)
            }
            catch (SocketException e) {
                println "${new Date().format('HH:mm:ss')} $e.localizedMessage [$options.serverIp:$options.serverPort]"
                Thread.sleep(5000)
            }
        }
        println "${new Date().format('HH:mm:ss')} Closing Application."
    }
}


